package visitor

import (
	"cuelang.org/go/cue/ast"
	"fmt"
	"strings"
)

type GoWriter struct {
	Ref     bool
	Types   []*TypeVisitor
	PkgName string
	imports []string
}

func NewWriter(pkgName string, ref bool) *GoWriter {
	return &GoWriter{
		Ref:     ref,
		Types:   []*TypeVisitor{},
		PkgName: pkgName,
		imports: []string{},
	}
}

func (v *GoWriter) visitType(field *ast.Field) {
	tv := &TypeVisitor{
		Ref:   v.Ref,
		field: field,
		attrs: []*TypeAttr{},
	}
	tv.visit()
	if tv.isType {
		v.Types = append(v.Types, tv)
	}
}
func (v *GoWriter) visitPackage(field *ast.Package) {
	v.PkgName = field.Name.Name
}
func (v *GoWriter) visitImport(field *ast.ImportDecl) {
	if specs := field.Specs; specs != nil {
		for _, spec := range specs {
			if spec.Name != nil && spec.Name.Name != "" {
				v.imports = append(v.imports, fmt.Sprintf("%s %s", spec.Name.Name, spec.Path.Value))
			} else {
				v.imports = append(v.imports, spec.Path.Value)
			}
		}
	}
}

func (v *GoWriter) Gen() *strings.Builder {
	ctx := &strings.Builder{}
	ctx.WriteString(fmt.Sprintf("package %s\n", v.PkgName))

	if len(v.imports) > 0 {
		ctx.WriteString("import (\n")
		for _, v := range v.imports {
			ctx.WriteString(fmt.Sprintf("    %s\n", v))
		}
		ctx.WriteString(")")
	}
	for _, v := range v.Types {
		v.write(ctx)
	}
	return ctx
}
